package visual;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.util.HashSet;
import java.util.Random;
import java.util.Set;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

/** 
 * This class can generate a sequence of saturated colors distinct to human eye (which is useful to draw plots). 
 * Instances with same seed produce same color sequences. 
 * 
 */ 
public class ColorGenerator { 
        private static final int ATTEMPTS = 10; 

        private final Random permRand; 
        private final Set<Color> usedColors; 

        public ColorGenerator() { 
                this.usedColors = new HashSet<Color>(1); 
                usedColors.add(Color.WHITE); 
                permRand = new Random(1); 
        } 

        public ColorGenerator(Set<Color> usedColors) { 
                this(usedColors, 1); 
        } 

        public ColorGenerator(Set<Color> usedColors, long seed) { 
                this.usedColors = new HashSet<Color>(usedColors); 
                permRand = new Random(seed); 
        } 

        public Color next() { 
                int maxDist = 0; 
                Color best = null; 
                for (int i = 0; i < ATTEMPTS; i++) { 
                        Color c = new Color(permRand.nextInt(256), permRand.nextInt(256), permRand.nextInt(256)); 
                        int dist = color2setDist(c, usedColors); 
                        if (dist > maxDist) { 
                                maxDist = dist; 
                                best = c; 
                        } 
                } 
                usedColors.add(best); 
                return best; 
        } 

// http://www.compuphase.com/cmetric.htm 
        private static int color2colorDist(Color x, Color y) { 
                int rmean = (x.getRed() + y.getRed()) / 2; 
                int r = x.getRed() - y.getRed(); 
                int g = x.getGreen() - y.getGreen(); 
                int b = x.getBlue() - y.getBlue(); 
                return (((512 + rmean) * r * r) >> 8) + 4 * g * g + (((767 - rmean) * b * b) >> 8); 
        } 

        private static int color2setDist(Color x, Set<Color> set) { 
                int minDist = Integer.MAX_VALUE; 
                for (Color y : set) { 
                        int dist = color2colorDist(x, y); 
                        minDist = dist < minDist ? dist : minDist; 
                } 
                return minDist; 
        } 

        // VISUAL TEST 
        private static final int SAMPLES_X = 30;
        private static final int SAMPLES_Y = 30;

        private static void showPalette() { 
                ColorGenerator generator = new ColorGenerator(); 
                JFrame frame = new JFrame("Color Generator"); 
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
                frame.getContentPane().setLayout(new GridLayout(SAMPLES_X, SAMPLES_Y)); 
                for (int i = 0; i < SAMPLES_X; i++) { 
                	for (int j=0; j < SAMPLES_Y; j++) {
                        JPanel panel = new JPanel(); 
                        panel.setPreferredSize(new Dimension(30, 30)); 
                        panel.setBackground(generator.next());
                        frame.getContentPane().add(panel); 
                	}
                } 
                frame.pack(); 
                frame.setVisible(true); 
        } 

        public static void main(String[] args) { 
                SwingUtilities.invokeLater(new Runnable() { 
                        public void run() { 
                                showPalette(); 
                        } 
                }); 
        } 

} 
